package linter.controller.model;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import linter.POJO.DO.UserFile;
import linter.POJO.DTO.UserDTO;
import linter.POJO.UtilDTO.ModelUtilDTO;
import linter.custom.ResultVO;
import linter.service.ModelUserService;
import linter.service.UserFileService;
import linter.service.UserService;
import linter.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;

import static linter.custom.CustomResultType.MODEL_TYPE_NOT_EXIST;

/**
 * @author 北煜
 */
@Slf4j
@Api(tags = "模型接口")
@RestController
@RequestMapping("/Model")
public class ModelController {

    @Resource
    UserService userService;
    @Resource
    ModelUserService modelUserService;
    @Resource
    UserFileService userFileService;

    @GetMapping("/show/getUserByUsername/{username}")
    @ApiOperation("根据用户名查找用户")
    public ResultVO<UserDTO> getUserByUsername(@PathVariable String username) {
        UserDTO userDTO = userService.getUserByUsername(username);
        return ResultVO.success(userDTO);
    }

    //TODO: 进行测试接口
    @PostMapping("/useLinearModel")
    @ApiOperation("进行线性回归模型")
    public ResultVO<String> useLinearModel( @RequestBody ModelUtilDTO modelUtilDTO ){
        log.info("调用线性回归模型");
        // 构造实例
        RestTemplate restTemplate = new RestTemplate();
        // 构造请求参数
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("featureColumns", modelUtilDTO.getFeatureColumns());
        params.add("featureColumn", modelUtilDTO.getFeatureColumn());
        params.add("testSizeUser", modelUtilDTO.getTestSizeUser());
        params.add("randomStateUser", modelUtilDTO.getRandomStateUser());
        String username = JwtUtils.getUserName((String) SecurityUtils.getSubject().getPrincipal());
        Long uuid = userService.getIdByUsername(username);
        QueryWrapper<UserFile> queryWrapper = new QueryWrapper<>();
        List<UserFile> userFile = userFileService.list(queryWrapper.eq("uuid", uuid).eq("is_delete", 0));

        // TODO：需要在UserFile表中加入一个完成字段，用来区别新的数据。历史回顾则从完成中的进行查找
        if (userFile.size() != 2) {
            return ResultVO.error("Expected exactly two files (train and test) per UUID, found " + userFile.size());
        }
        String trainFilename = null;
        String testFilename = null;
        for (UserFile file : userFile) {
            switch (file.getFiletype()) {
                case "train":
                    trainFilename = file.getFilename();
                    break;
                case "test":
                    testFilename = file.getFilename();
                    break;
                default:
                    return ResultVO.error(MODEL_TYPE_NOT_EXIST);
            }
        }
        // 确保找到了训练和测试文件
        if (trainFilename == null || testFilename == null) {
            return ResultVO.error("Both train and test files are required.");
        }
        params.add("trainFile", trainFilename);
        params.add("testFile", testFilename);

        HttpHeaders headers = new HttpHeaders();
        // 设置Content-Type为表单类型
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);

        // 发送POST请求
        ResponseEntity<String> response = restTemplate.postForEntity("http://127.0.0.1:8888/Linear",
                requestEntity, String.class);
        // 处理响应结果
        if (response.getStatusCode().is2xxSuccessful()) {
            // 请求成功
            String result = response.getBody();
            System.out.println("result: ");
            System.out.println(result);
            // 处理结果 TODO: 返回的值是一个json对象
            String main = restTemplate.postForObject("http://127.0.0.1:8888/LinearMain", null ,String.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                // 请求成功
                System.out.println(main);
                // 处理结果
                return ResultVO.success(modelUserService.saveDataLinear(main, params, uuid));
            }
        }
        return ResultVO.error("请求失败");
    }

    @GetMapping("/useLogisticRegressionModel")
    @ApiOperation("进行逻辑回归模型")
    public ResultVO<String> useLogisticRegressionModel( @RequestParam ModelUtilDTO modelUtilDTO){
        log.info("调用逻辑回归模型");
        // 构造实例
        RestTemplate restTemplate = new RestTemplate();
        // 构造请求参数
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("featureColumns", modelUtilDTO.getFeatureColumns());
        params.add("featureColumn", modelUtilDTO.getFeatureColumn());
        params.add("testSizeUser", modelUtilDTO.getTestSizeUser());
        params.add("randomStateUser", modelUtilDTO.getRandomStateUser());
        String username = JwtUtils.getUserName((String) SecurityUtils.getSubject().getPrincipal());
        Long uuid = userService.getIdByUsername(username);
        UserFile userFile = userFileService.getById(uuid);
        for(int i = 0; i < 2; i++){
            switch (userFile.getFiletype()) {
                case "train":
                    params.add("trainFile", userFile.getFilename());
                    break;
                case "test":
                    params.add("testFile", userFile.getFilename());
                    break;
                default:
                    i = 2;
                    return ResultVO.error(MODEL_TYPE_NOT_EXIST);
            }
        }
        // 发送POST请求
        ResponseEntity<String> response = restTemplate.postForEntity(
                "http://127.0.0.1:8888/LogisticRegression", params, String.class);
        // 处理响应结果
        if (response.getStatusCode().is2xxSuccessful()) {
            // 请求成功
            String result = response.getBody();
            System.out.println("result: ");
            System.out.println(result);
            // 处理结果
            String main = restTemplate.postForObject(
                    "http://127.0.0.1:8888/LogisticRegressionMain", null ,String.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                // 请求成功
                System.out.println(main);
                // 处理结果
                return ResultVO.success(modelUserService.saveDataLM(main, params, uuid));
            }
        }
        return ResultVO.error("请求失败");
    }
}
